/**
 *****************************************************************************
 * DESC ：. 
 * Author : Junwei Zhang 
 * CREATEDATE ：2012-6-25 
 * MODIFYLIST ：       	Name 			 Date 			Reason/Contents
 * 				------------------------------------------------------ 
 * 				 	Junwei Zhang     2012-6-25		Created.
 ****************************************************************************
 **/
package com.me.client;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import javax.swing.ListModel;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;

import com.me.client.JTalkClient.MemberData;
import com.me.server.JTalkerMember;

/**
 * 
 * <br/>
 * 上午8:47:42 2012-6-25
 * 
 * @Author <a href="mailto:mestudying@sina.com">Junwei Zhang</a><br/>
 **/
public class JTalkChat extends JFrame implements JTalkClientCommandInterface {

	private static final String ownMessageMarker = "<<<<<ME>>>>>";;

	private ClassLoader cl = null;

	private JPanel jPanelWhole = null;
	private JPanel jPanelChatRoomUser = null;
	private JPanel jPanelTalkAreaSouth = null;
	private JPanel jPanelHistory = null;
	private JScrollPane jScrollPaneMsg = null;
	private JScrollPane jScrollPaneTextArea = null;
	private JScrollPane jScrollPaneChatRoomUser = null;

	private JToolBar jToolBar = null;
	private JButton jButtonSendMsg = null;
	private JButton jButtonSendFile = null;
	private JButton jButtonClearHistory = null;
	private JButton jButtonView = null;
	private JButton jButtonHistoryUp = null;
	private JButton jButtonHistoryDown = null;

	private JTextArea jTextAreaInput = null;
	private JLabel jLabelStatus = null;
	private JList jListChatRoomUser = null;
	private JEditorPane jEditorPaneDisplayMsg = null;
	/**
	 * private Socket socket = null; private PrintWriter out = null; private BufferedReader in = null; private String
	 * serverAddress = "localhost"; private int serverPort = 4443;
	 */
	private List<String> historyList = null;
	private MemberData memberData = null;
	private JTalkClientFront parentClientFront = null;

	private boolean isChatRoom = false;
	private String[] chatRoomUsers = { "Loading..." };

	private MemberListModel memberListModel = null;

	private static String msgSuffix = "【Message From Client】---";

	public JTalkChat(JTalkClientFront parent, MemberData memberData) {
		this.memberData = memberData;
		this.parentClientFront = parent;
		this.historyList = new ArrayList<String>();
		this.initComponents();
		this.requestFocus();
		if (this.memberData.type.equals(JTalkerMember.USER_TYPE_CHATROOM)) {
			this.isChatRoom = true;
			this.memberListModel = new MemberListModel();
			this.jListChatRoomUser.setModel(this.memberListModel);
			this.jPanelChatRoomUser.setVisible(true);
			this.jLabelStatus.setText("Chatroom: " + memberData.short_name + " @ " + memberData.ip);
		} else {
			this.jPanelChatRoomUser.setVisible(false);
			this.jLabelStatus.setText("Chat with " + memberData.short_name + " @ " + memberData.ip);
		}
		this.setLocationRelativeTo(null);
		this.parentClientFront.theClient.registerForCommandResponse(this);
		// this.setVisible(true);
		/**
		 * -------------------Connect Server.--------------------------- try { socket = new Socket(serverAddress,
		 * serverPort); out = new PrintWriter(socket.getOutputStream(), true); in = new BufferedReader(new
		 * InputStreamReader(socket.getInputStream())); // println("I am a client."); String allMessage = null; String
		 * msgFromServer = null; while((msgFromServer = in.readLine()) != null){ allMessage = "";
		 * messageList.add(msgFromServer); for(String msg : messageList){ allMessage += msg + "\r\n"; }
		 * jEditorPaneDisplayMsg.setText(allMessage); } // System.out.println("---------Client Message---------" +
		 * msgFromServer); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }
		 */
	}

	/**
	 * Send the message.
	 */
	private void sendMessage() {
		// TODO Auto-generated method stub
		if(!this.memberData.isConnected()){
			JOptionPane.showMessageDialog(this, "The User is offline - you can't send a message!", 
					"User is OFFLINE", JOptionPane.INFORMATION_MESSAGE);
			return;
		}
		String message = this.jTextAreaInput.getText();
		if (message.length() > 0) {
			// out.println(message);
			this.historyList.add(message);
			if (!this.memberData.type.equals(JTalkParser.USER_TYPE_CHATROOM)) {
				this.memberData.addMessage(ownMessageMarker + " " + message, "my Message", "normal");
			}
			this.parentClientFront.theClient.sendMessage(message, this.memberData.name);
			this.updateWindow();
		}
		this.jTextAreaInput.setText("");
	}

	/**
	 * 发送文件.
	 */
	private void sendFile() {
		// TODO Auto-generated method stub
		Base64Handler handler = new Base64Handler(this);
		Base64Handler.EncodedFileObject fileObj = handler.getEncodedFile();
		if (fileObj != null) {
			this.parentClientFront.theClient.sendMessage(fileObj.data, this.memberData.name, "file", fileObj.fileName);
//			System.out.println("--------sendFile1-------" + Thread.currentThread());
//			try {
//				Thread.sleep(1000);
//			} catch (InterruptedException e) {
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//			}
//			System.out.println("--------sendFile2-------" + Thread.currentThread());
			this.memberData.addMessage(ownMessageMarker + " " + "<i>---Sending File--- (" + fileObj.fileName + ")</i>",
					"Sending File", "normal");
		} else {
			JOptionPane.showMessageDialog(this, "Can't send file:\n" + handler.lastError, "Can't send file",
					JOptionPane.ERROR_MESSAGE);
		}
	}

	/**
	 * 发送消息.
	 * 
	 * @param message
	 */
	private void println(String message) {
		// out.println(message + msgSuffix);
	}

	/**
	 * 初始化组件.
	 */
	private void initComponents() {
		jPanelWhole = new JPanel();
		jPanelWhole.setLayout(new BorderLayout());
		cl = JTalkChat.class.getClassLoader();
		/** -------------------Initialize Tool Bar.--------------------------- */
		this.initToolBar(cl);

		/** -------------------Initialize Input Area.--------------------------- */
		this.initInputArea();

		/** -------------------Initialize Message Display.--------------------------- */
		this.initMessageDisplay();

		/** -------------------Initialize Self.--------------------------- */
		this.initSelf();
	}

	private void initSelf() {
		this.getContentPane().add(jPanelWhole, BorderLayout.CENTER);
		this.getContentPane().add(jToolBar, BorderLayout.NORTH);
		// this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.addWindowListener(new WindowAdapter() {

			@Override
			public void windowClosing(WindowEvent e) {
				exitForm(e);
			}

		});
		this.setTitle(this.memberData.short_name);
		this.setSize(300, 300);
		this.pack();
	}

	private void initMessageDisplay() {
		jScrollPaneMsg = new JScrollPane();
		jEditorPaneDisplayMsg = new JEditorPane("text/html; charset=UTF-8", null);
		jEditorPaneDisplayMsg.setEditable(false);
		jScrollPaneMsg.setViewportView(jEditorPaneDisplayMsg);
		jPanelWhole.add(jScrollPaneMsg, BorderLayout.CENTER);

		jPanelChatRoomUser = new JPanel();
		jPanelChatRoomUser.setLayout(new BorderLayout());
		jScrollPaneChatRoomUser = new JScrollPane();
		jListChatRoomUser = new JList();
		jScrollPaneChatRoomUser.setViewportView(jListChatRoomUser);
		jPanelChatRoomUser.add(jScrollPaneChatRoomUser, BorderLayout.CENTER);
		jPanelWhole.add(jPanelChatRoomUser, BorderLayout.EAST);
	}

	private void initToolBar(ClassLoader cl) {
		jToolBar = new JToolBar();

		jButtonSendMsg = new JButton();
		jButtonSendMsg.setIcon(new ImageIcon(cl.getResource("com/jtalker/rs/icons/mail_send.png")));
		jButtonSendMsg.setToolTipText("Send Meddage Now.");
		jButtonSendMsg.setMargin(new Insets(1, 2, 1, 2));
		jButtonSendMsg.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				sendMessage();
			}

		});
		jToolBar.add(jButtonSendMsg);

		jButtonSendFile = new JButton();
		jButtonSendFile.setIcon(new ImageIcon(cl.getResource("com/jtalker/rs/icons/file_send.png")));
		jButtonSendFile.setToolTipText("Send File");
		jButtonSendFile.setMargin(new Insets(1, 2, 1, 2));
		jButtonSendFile.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				sendFile();
			}
		});
		jToolBar.add(jButtonSendFile);
		jToolBar.addSeparator();

		jButtonClearHistory = new JButton();
		jButtonClearHistory.setIcon(new ImageIcon(cl.getResource("com/jtalker/rs/icons/editdelete.png")));
		jButtonClearHistory.setToolTipText("Clear History");
		jButtonClearHistory.setMargin(new Insets(1, 2, 1, 2));
		jToolBar.add(jButtonClearHistory);

		jButtonView = new JButton();
		jButtonView.setIcon(new ImageIcon(cl.getResource("com/jtalker/rs/icons/toggle_view.png")));
		jButtonView.setToolTipText("Toggle View");
		jButtonView.setMargin(new Insets(1, 2, 1, 2));
		jToolBar.add(jButtonView);
	}

	private void initInputArea() {
		jPanelTalkAreaSouth = new JPanel();
		jPanelTalkAreaSouth.setLayout(new BorderLayout());
		jPanelTalkAreaSouth.setPreferredSize(new Dimension(400, 85));

		jScrollPaneTextArea = new JScrollPane();

		jTextAreaInput = new JTextArea();
		jTextAreaInput.setMinimumSize(new Dimension(20, 20));
		jTextAreaInput.setPreferredSize(new Dimension(100, 20));
		jTextAreaInput.setLineWrap(true);
		jTextAreaInput.setToolTipText("Enter your message here.");
		jTextAreaInput.setWrapStyleWord(true);
		jScrollPaneTextArea.setViewportView(jTextAreaInput);
		jPanelTalkAreaSouth.add(jScrollPaneTextArea, BorderLayout.CENTER);

		jPanelHistory = new JPanel();
		jPanelHistory.setLayout(new GridLayout(2, 1));
		jPanelHistory.setPreferredSize(new Dimension(50, 100));

		jButtonHistoryUp = new JButton();
		jButtonHistoryUp.setIcon(new ImageIcon(cl.getResource("com/jtalker/rs/icons/uparrow.png")));
		jButtonHistoryUp.setMargin(new Insets(0, 0, 0, 0));
		jButtonHistoryUp.setToolTipText("History Up");
		jPanelHistory.add(jButtonHistoryUp);

		jButtonHistoryDown = new JButton();
		jButtonHistoryDown.setIcon(new ImageIcon(cl.getResource("com/jtalker/rs/icons/downarrow.png")));
		jButtonHistoryDown.setMargin(new Insets(0, 0, 0, 0));
		jButtonHistoryDown.setToolTipText("History Down");
		jPanelHistory.add(jButtonHistoryDown);
		jPanelTalkAreaSouth.add(jPanelHistory, BorderLayout.EAST);

		jLabelStatus = new JLabel();
		jLabelStatus.setText("Chat with " + this.memberData.short_name + "@" + this.memberData.ip);
		jPanelTalkAreaSouth.add(jLabelStatus, BorderLayout.SOUTH);

		jPanelWhole.add(jPanelTalkAreaSouth, BorderLayout.SOUTH);
	}

	/**
	 * 更新聊天窗口.
	 */
	public void updateWindow() {
		if (!this.isVisible()) {
			return;
		}
		//synchronized (this.memberData) { // 同步 this.memberData
			StringBuffer messageLines = new StringBuffer();
			for (int i = 0; i < this.memberData.numOfMessages(); i++) {
				String msg = this.memberData.getMessage(i);
				if(msg != null){
					String date = this.memberData.getDate(i);
					msg = this.makeTemplate(this.memberData.short_name, date, msg);
					messageLines.append(msg);
				}
				this.memberData.hasNewMessage = false;
			}
			String s = messageLines.toString().replace(ownMessageMarker, "");
			if (s.length() > 0) {
				this.jEditorPaneDisplayMsg.setText(s);
			}
			/** 如果是聊天室,则向服务器请求聊天室成员. */
			int num = this.jEditorPaneDisplayMsg.getDocument().getLength();
			this.jEditorPaneDisplayMsg.setCaretPosition(num);
			if (this.isChatRoom) {
				this.checkChatroomUsers();
			}
			// System.out.println("--------updateWindow1-------" + Thread.currentThread());
			if(this.memberData.saveFiles()){
				// System.out.println("---------this.memberData----------" + this.memberData.short_name);
				this.memberData.addMessage("<i>---File received---</i>", "my Message", "normal");
			}
		//}
	}

	/**
	 * 获取聊天室内的成员.
	 */
	private void checkChatroomUsers() {
		if (!this.isChatRoom) {
			return;
		}
		this.parentClientFront.theClient.sendMessage("std::getChatRoomUsers(\"" + this.memberData.short_name + "\")",
				null, "command", null, "getchatusers01");
	}

	/**
	 * 设置消息显示格式.
	 * 
	 * @param short_name
	 * @param date
	 * @param message
	 * @return
	 */
	private String makeTemplate(String userName, String date, String message) {
		// TODO Auto-generated method stub
		String retVal = "";
		if (!message.startsWith(ownMessageMarker)) {
			retVal += "<table border=\"0\" width=\"100%\"><tr><td bgcolor=\"#cccccc\">" + "<font color=\"black\"><b>"
					+ userName + "</b>" + " (" + date + ")" + "</font></td></tr></table><font color=\""
					+ this.parentClientFront.theClient.guiTextColor + "\">" + message + "</font><br><br>";
		} else {
			retVal += "<font color=\""
					+ parentClientFront.theClient.guiTextColor
					+ "\">"
					+ message.replaceFirst(ownMessageMarker,
							"<table border=\"0\" width=\"100%\"><tr><td bgcolor=\"#ffff99\"><font color=\"black\"><b>"
									+ this.parentClientFront.theClient.userName + "</b> (" + date
									+ ")</font></td></tr></table>");
			retVal += "</font><br><br>";
		}
		return retVal;
	}

	/**
	 * 退出聊天框.
	 * 
	 * @param e
	 */
	private void exitForm(WindowEvent e) {
		this.dispose();
	}

	@Override
	public boolean setCommandAnswer(String messageID, String sender, String content) {
		// TODO Auto-generated method stub
		boolean retVal = false;
		if (messageID.equals("getchatusers01")) {
			String lastResponse = content;
			if (lastResponse == null) {
				return true;
			}
			this.chatRoomUsers = lastResponse.split(";;");
			if (this.memberListModel != null) {
				this.memberListModel.propertyChanged();
			}
			retVal = true;
		}else if(messageID.equals("rmchatuser01")){
			this.checkChatroomUsers();
			return true;
		}
		return retVal;
	}

	/**
	 * JList model for chat-room.
	 * 
	 * @author Administrator
	 * 
	 */
	public class MemberListModel implements ListModel {

		private ListDataListener listener = null;

		public void propertyChanged() {
			int length = 0;
			if (chatRoomUsers != null) {
				length = chatRoomUsers.length;
			}
			this.listener.contentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, length, 0));
		}

		@Override
		public int getSize() {
			if (chatRoomUsers != null) {
				return chatRoomUsers.length;
			} else {
				return 0;
			}
		}

		@Override
		public Object getElementAt(int index) {
			return chatRoomUsers[index];
		}

		@Override
		public void addListDataListener(ListDataListener l) {
			this.listener = l;
		}

		@Override
		public void removeListDataListener(ListDataListener l) {
			// TODO Auto-generated method stub

		}

	}

}
